package org.geekbang.thinking.in.spring.bean.lifecycle;

import org.geekbang.thinking.in.spring.ioc.overview.domain.SuperUser;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.util.ObjectUtils;

/**
 * @author: wangsiqi
 * @date: 2021/10/31
 */
class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
            // 拦截 superUser, 把需要配置的 superUser Bean 覆盖
            // 不执行后续 #postProcessAfterInstantiation 和 #postProcessProperties的回调
            return new SuperUser();
        }
        return null;    // 保持 Spring IOC 容器的实例化操作
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("user", beanName) && User.class.equals(bean.getClass())) {
            // 拦截 user, "user" 对象不进行通过配置赋值（配置元信息 -> 属性赋值）
            // 这里手动赋值，返回 false则不执行后续 #postProcessProperties的回调
            User user = (User) bean;
            user.setId(330L);
            user.setName("330name");
            return false;
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("userHolder", beanName) && bean.getClass().equals(UserHolder.class)) {
            // 对 "userHolder" Bean 进行拦截
            // 假设 <property name="number" value="1000" /> 配置的话，那么 PropertyValues 就包含 PropertyValue(number=1)
            MutablePropertyValues propertyValues = null;
            if (pvs instanceof MutablePropertyValues) {
                propertyValues = (MutablePropertyValues) pvs;
            } else {
                propertyValues = new MutablePropertyValues();
            }
            propertyValues.addPropertyValue("number", 2000);    // 替换
            propertyValues.addPropertyValue("desc", "the user holder version2"); // 添加
            return propertyValues;
        }
        return null;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals("userHolder", beanName) && bean.getClass().equals(UserHolder.class)) {
            UserHolder userHolder = (UserHolder) bean;
            userHolder.setDesc("user holder version3");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (ObjectUtils.nullSafeEquals(beanName, "userHolder") && bean.getClass().equals(UserHolder.class)) {
            UserHolder userHolder = (UserHolder) bean;
            userHolder.setDesc("user holder version7");
            System.out.println("postProcessAfterInitialization(): " + userHolder.getDesc());
        }
        return bean;
    }
}
